/*******************************************************************************
 * Copyright 2010 DemandSpot
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.demandspot.client.table;

import java.util.List;

import com.google.gwt.gen2.table.client.FixedWidthFlexTable;
import com.google.gwt.gen2.table.client.ScrollTable;
import com.google.gwt.gen2.table.client.SelectionGrid.SelectionPolicy;
import com.google.gwt.gen2.table.override.client.FlexTable.FlexCellFormatter;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;

public class DataScrollTable<RowModel> extends ScrollTable {
	public enum FooterWidgetLocation {LEFT, CENTER, RIGHT};
	
	private DataTable<RowModel> dataTable;
	private FooterTableBodyWidget footerBody;
	
	public static <T> DataScrollTable<T> createTable(List<T> data, List<CellRenderer<T, ?>> renderers, FixedWidthFlexTable headerTable) {
		return createTable(data, renderers, headerTable, SelectionPolicy.CHECKBOX);
	}
	
	public  static <T> DataScrollTable<T> createTable(List<T> data, List<CellRenderer<T, ?>> renderers, FixedWidthFlexTable headerTable, SelectionPolicy selectionPolicy) {
		DataTable<T> dataTable = new DataTable<T>(data, renderers, new String[]{"dark", "light"});
		if (selectionPolicy == null) {
			dataTable.setSelectionEnabled(false);
		} else {
			dataTable.setSelectionPolicy(selectionPolicy);
		}
		
		DataScrollTable<T> scrollTable = new DataScrollTable<T>(dataTable, headerTable, renderers.size());
		
		boolean needToBuildFilter = false;
		for (int i=0; i < renderers.size(); i++) {
	    	CellRenderer<T,?> cellRenderer = renderers.get(i);
	    	scrollTable.setColumnSortable(i, cellRenderer.isSortable());
	    	int width = cellRenderer.getWidth();
	    	if (width > 0) {
	    		scrollTable.setColumnWidth(i, width);
				scrollTable.setPreferredColumnWidth(i, width);
	    	}
	    	
	    	if (cellRenderer.getFilterOperations() != null && cellRenderer.getFilterOperations().length > 0) {
	    		needToBuildFilter = true;
	    	}
		}
		
		if (needToBuildFilter) {
			scrollTable.addWidgetToFooter(new FilterWidget<T>(renderers, dataTable), FooterWidgetLocation.LEFT);
		}
		
		scrollTable.setResizePolicy(ScrollTable.ResizePolicy.FILL_WIDTH);
		
		return scrollTable;
	}
	
	private DataScrollTable(DataTable<RowModel> dataTable, FixedWidthFlexTable headerTable, int numOfCol) {
		super(dataTable, headerTable);
		this.dataTable = dataTable;
		this.footerBody = new FooterTableBodyWidget();
		footerBody.setWidth("100%");
		
		FixedWidthFlexTable footerTable = new FixedWidthFlexTable();
		FlexCellFormatter footerFormatter = footerTable.getFlexCellFormatter();
		footerTable.setWidget(0, 0, footerBody);
		footerFormatter.setColSpan(0, 0, numOfCol);
		this.setFooterTable(footerTable);
	}

	public List<RowModel> getSelectedModels() {
		return dataTable.getSelectedModels();
	}

	public void deselectAllRows() {
		dataTable.deselectAllRows();
	}

	public void selectAllRows() {
		dataTable.selectAllRows();
	}

	public List<RowModel> getAllModels() {
		return dataTable.getAllModels();
	}

	public List<RowModel> getFilterdModels() {
		return dataTable.getFilterdModels();
	}

	public void addModel(RowModel rowModel) {
		dataTable.addModel(rowModel);
	}
	
	public void addModels(List<RowModel> rowModels) {
		dataTable.addModels(rowModels);
	}
	
	public void addWidgetToFooter(Widget widget, FooterWidgetLocation widgetLocation) {
		footerBody.addWidget(widget, widgetLocation);
	}
	
	public void removeFilter(FilterRow<RowModel> filter) {
		dataTable.removeFilter(filter);
	}

	public void removeModel(RowModel rowModel) {
		dataTable.removeModel(rowModel);
	}

	public void removeAllModels() {
		dataTable.removeAllModels();
	}
	
	public void removeRow(int row) {
		dataTable.removeRow(row);
	}

	public void buildTable() {
		dataTable.buildTable();
	}

	public int getSortedColumn() {
		return dataTable.getSortedColumn();
	}

	public boolean isSortDirection() {
		return dataTable.isSortDirection() || getSortedColumn() < 0;
	}

	private static class FooterTableBodyWidget extends Composite {
		private Grid body = new Grid(1, 3);
		
		public FooterTableBodyWidget() {
			initWidget(body);
			body.setWidth("100%");
			body.setCellPadding(0);
			body.setCellSpacing(0);
			
			CellFormatter cellFormatter = body.getCellFormatter();
			
			cellFormatter.setHorizontalAlignment(0, 0, HasAlignment.ALIGN_LEFT);
			cellFormatter.setHorizontalAlignment(0, 1, HasAlignment.ALIGN_CENTER);
			cellFormatter.setHorizontalAlignment(0, 2, HasAlignment.ALIGN_RIGHT);
			
			body.setWidget(0, 0, createContainer());
			body.setWidget(0, 1, createContainer());
			body.setWidget(0, 2, createContainer());
		}
		
		private Panel createContainer() {
			HorizontalPanel panel = new HorizontalPanel();
			return panel;
		}
		
		public void addWidget(Widget widget, FooterWidgetLocation widgetLocation) {
			Panel panel = null;
			
			switch(widgetLocation) {
				case LEFT:
					panel = (Panel) body.getWidget(0, 0);
					break;
				case CENTER:
					panel = (Panel) body.getWidget(0, 1);
					break;
				case RIGHT:
					panel = (Panel) body.getWidget(0, 2);
					break;
			}
			
			panel.add(widget);
		}
	}
	
}
